package com.hq.distributed;

/**
 * 分布式锁总结几点：
 * 1、互斥行：要做到多线程之间的原子性。
 * 1.1、自己实现：通过中间件 redis setnx设置一个值进去，如果能成功就返回一个1 失败则返回0，基于这一思想，多线程进入后
 * 拿不到锁的线程就直接返回一个错误提示即可。（业务中是不会直接返回的 在第4点有说明 这里是非阻塞操作）。
 * 1.2、框架实现：redission redis官方提供的分布式锁组件，该组件通过getLock方法获取到类似ReentrantLock的RLock锁，封装了
 * lock方法   tryLock  unlock方法 实现 可重入锁、阻塞锁、非阻塞锁、公平锁、防止死锁的功能。
 * 2、要防止死锁：1.1中 在线程执行的过程中，这台服务器挂了，那么redis这个锁一直得不到释放，这里就是形成死锁，如何解决呢？
 * 在设置值的时候，带上超时时间，要用原子性的方法 设置值和设置超时时间是原子性操作 setnx提供相关api。
 * 3、要可重入:  这个可以参考ReentrantLock的实现，线程进入后再次去获取锁，会把锁的状态设置为+1（持有锁状态为1）。
 * 4、可以阻塞和非阻塞：1.1中拿不到锁的线程，直接的返回了，这不符合实际业务中的需求，通常来说只会让他等待一定的时间后去
 * 去拿到锁，在执行它的任务。这里也是类似ReentrantLock 进入一个死循环，在循环体中不断的尝试获取锁。
 * 5、要对锁失效的场景有一定了解；这里要介绍一下redis的集群同步过程，线程在执行setnx方法 redis判断有无值后就会返回给你信息，
 * 然后在异步的方式，同步给其他redis服务器。 那么在这个过程中，如果一个线程还在持有锁的时候master挂了，那么后面的线程
 * 在尝试获取锁的时候，是能从其他redis获取到值（这个时候还没同步到数据）。这样就会出现超卖线程。
 * 5.1、如何解决呢？  可以用集群的方式，或者用zk，从zk中拿锁，他会先同步给他其他节点，并且节点数超过一半的时候才会
 * 返回给你值。
 * <p>
 * 存在问题：在加锁过程中 业务死循环,那就导致锁得不到释放
 * CAP： Consistency 一致性   Availability 可用性 Partition tolerance分区容错性
 *
 * @author MAIBENBEN
 */
public class DistributedLock {

}
